<?php

namespace App\Services;

use App\Models\WxCardMemberLevel;
use Illuminate\Support\Facades\Cache;

/**
 * 微信会员卡服务类
 * @package App\Services
 */
class WxCardMemberLevelService
{
    const COMMON_CARD_NORMAL = 'common_card_normal';
    const COMMON_CARD_VIP = 'common_card_vip';

    protected $levelKeyList;

    /**
     * 构造函数
     */
    public function __construct()
    {
        $this->levelKeyList = [
            self::COMMON_CARD_NORMAL => '[通用会员卡]普通会员',
            self::COMMON_CARD_VIP => '[通用会员卡]VIP会员',
        ];
    }

    /**
     * 获取会员标识列表，开发时需在代码中新增对应的会员业务类
     * @return array
     */
    public function getLevelKeyList()
    {
        $list = [];
        if (!empty($this->levelKeyList)) {
            foreach ($this->levelKeyList as $k => $v) {
                $list[] = ['type' => $k, 'name' => $v];
            }
        }
        return $list;
    }

    /**
     * 获取会员标识名称
     * @param $levelKey
     * @return mixed|string
     */
    public function getLevelKeyName($levelKey)
    {
        return isset($this->levelKeyList[$levelKey]) ? $this->levelKeyList[$levelKey] : '';
    }

    /**
     * 获取分组用户等级列表，已卡券基础ID为分组key
     * @return array
     */
    public function getGroupListByBaseId()
    {
        $levelList = WxCardMemberLevel::orderBy('order_num', 'ASC')->orderBy('id', 'ASC')->get()->toArray();
        $newLevelList = [];
        foreach ($levelList as $v) {
            $newLevelList[(int)$v['card_base_id']][] = $v;
        }
        return $newLevelList;
    }

    /**
     * 获取缓存中的分组key
     * @param bool $isRefresh
     * @return mixed
     */
    public function getGroupCacheList($isRefresh = false)
    {
        $cacheKey = 'wxcard_memberlevels_group_bycardbaseid';
        $cacheData = Cache::get($cacheKey);
        if (!$cacheData || $isRefresh) {
            $cacheData = $this->getGroupListByBaseId();
            Cache::put($cacheKey, $cacheData, 60);
        }
        return $cacheData;
    }

    /**
     * 获取缓存中中的分类列表
     * @param $type
     * @param bool $isRefresh
     * @return mixed
     */
    public function getList($cardBaseId)
    {
        $groupCacheList = $this->getGroupCacheList();
        return isset($groupCacheList[$cardBaseId]) ? $groupCacheList[$cardBaseId] : [];
    }

    /**
     * 保存分类
     * @param $request
     * @return bool
     */
    public function save($request)
    {
        if ($request->id) {
            $levelModel = WxCardMemberLevel::find($request->id);
        } else {
            $levelModel = new WxCardMemberLevel;
        }
        $levelModel->card_base_id = (int)$request->card_base_id;
        if (empty($levelModel->card_base_id)) {
            throw new \Exception('请指定等级所属会员卡');
        }
        $levelModel->key = $request->key ?? '';
        $levelModel->name = $request->name ?? '';
        $levelModel->description = $request->description ?? '';
        $levelModel->background_pic_url = $request->background_pic_url ?? '';
        $levelModel->give_bonus = $request->give_bonus ?? '';
        $levelModel->give_coupon = $request->give_coupon ?? '';
        $levelModel->order_num = (int)$request->order_num ?? 0;
        $rs = $levelModel->save();
        //刷新缓存
        $this->getGroupCacheList(true);
        return $rs;
    }

    /**
     * 删除分类
     * @param $catId
     * @return mixed
     */
    public function del($id)
    {
        $levelModel = WxCardMemberLevel::findOrFail($id);
        $rs = $levelModel->delete();
        //刷新缓存
        $this->getGroupCacheList(true);
        return $rs;
    }

    /**
     * 校验检查会员等级是否有效，返回指定数据
     * @param $cardBaseId
     * @param $userOpenId
     * @return bool
     */
    public function checkValid($cardBaseId, $userOpenId)
    {
        $levelList = $this->getList($cardBaseId);
        //反转等级顺序，从高级到低级开始校验
        $levelList = !empty($levelList) ? array_reverse($levelList) : [];
        foreach ($levelList as $levelData) {
            $levelObj = __NAMESPACE__ . '\WxCardMemberLevel\\' . camelizeClass($levelData['key']);
            if (class_exists($levelObj)) {
                $checkValid = (new $levelObj($levelData))->checkValid($userOpenId);
                if ($checkValid) {
                    return $checkValid;
                }
            }
        }
        return false;
    }
}